package com.ofd.soft.xml;

import java.awt.Font;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import com.ofd.soft.util.ImageBase64Utils;
import com.ofd.soft.util.Loadfont;
import com.ofd.soft.util.UnpackZip;
import com.ofd.soft.xml.bean.ContentXmlBean;
import com.ofd.soft.xml.bean.DocumentResBean;
import com.ofd.soft.xml.bean.DocumentXmlBean;
import com.ofd.soft.xml.bean.FontBean;
import com.ofd.soft.xml.bean.ImageObjectBean;
import com.ofd.soft.xml.bean.LayerBean;
import com.ofd.soft.xml.bean.MultiMediaBean;
import com.ofd.soft.xml.bean.OfdXmlBean;
import com.ofd.soft.xml.bean.PublicResXmlBean;
import com.ofd.soft.xml.bean.TextObjectBean;
import com.ofd.soft.xml.bean.physicalBoxXmlBean;

public class ReadXML {

//	ofd 基础文件，名称固定
	private static final String OFD_XML_NAME = "OFD.xml";

	public static OfdXmlBean ofd2H5(OfdXmlBean ofdXmlBean, String folderPath, String fileName) throws DocumentException {
		String filePath = folderPath + File.separator + fileName;
		
//		复制并重命名
		String copyAndRenameFile = copyAndRenameFile(filePath);
		
//		随机数文件夹路径
		folderPath = folderPath + File.separator + "UUID_Folder" +  File.separator +UUID.randomUUID().toString();
		
//		解压文件
		UnpackZip.unZip(new File(copyAndRenameFile), folderPath);
		
//		获取跟文件 OFD.XML 中获取DocRoot标签
		getRootXmlPathList(folderPath, ofdXmlBean);
		String docRootFolderName = null;
		String thisFilePath = null;
		String rootXmlPath = ofdXmlBean.getDocRoots().getPath();
		
//		获取所有根节点，应该只有一个
		docRootFolderName = rootXmlPath.split("/")[0];
		
//			读取文档跟节点  Document.XML
		readDocument(folderPath + File.separator + rootXmlPath, ofdXmlBean);
		
//		创建资源id与资源值键值对
		Map<String,String> resourcesMap =  new HashMap<String, String>();
		
//			读取文档中的公共资源序列  PublicRes
		PublicResXmlBean publicRes = ofdXmlBean.getDocRoots().getPublicRes();
		readPubilcRes(folderPath + File.separator + docRootFolderName + File.separator + publicRes.getPath(),publicRes,resourcesMap);
		
//		读取文档中的文档资源序列
		DocumentResBean documentRes = ofdXmlBean.getDocRoots().getDocumentRes();
		readDocumentRes(documentRes, folderPath + File.separator + docRootFolderName + File.separator+ documentRes.getPath(),resourcesMap);
		
//		读取文档内容
		List<ContentXmlBean> contentXmlBeanList = ofdXmlBean.getDocRoots().getContentXmlBeanList();
		for (ContentXmlBean contentXmlBean : contentXmlBeanList) {
			thisFilePath = folderPath + File.separator + docRootFolderName + File.separator + contentXmlBean.getPath();
			getContent(thisFilePath, contentXmlBean, ofdXmlBean,resourcesMap);
		}
		
//		删除临时zip文件
//		new File(copyAndRenameFile).delete();
//		删除zip 解压文件
//		new File(folderPath).delete();

		return ofdXmlBean;
	}

	public static void readDocumentRes(DocumentResBean documentResBean, String documentResPath,Map<String,String> resourcesMap) throws DocumentException {
		SAXReader reader = new SAXReader();
		File file = new File(documentResPath);
		Document document = reader.read(file);
		Element root = document.getRootElement();
//		读取前置路径
		String baseLocPath = root.attributeValue("BaseLoc");
//		解析图片文件夹路径
		String imageFolder = documentResPath.substring(0, documentResPath.lastIndexOf(File.separator)) + File.separator
				+ baseLocPath;
		List<Element> multiMedias = root.element("MultiMedias").elements();
		List<MultiMediaBean> multiMediaBeanList = new ArrayList<MultiMediaBean>();
		MultiMediaBean multiMediaBean = null;
		for (Element multiMedia : multiMedias) {
			multiMediaBean = new MultiMediaBean();
			multiMediaBean.setId(multiMedia.attributeValue("ID"));
			multiMediaBean.setType(multiMedia.attributeValue("Type"));
			multiMediaBean.setMediaFile(imageFolder + File.separator + multiMedia.elementText("MediaFile"));
			multiMediaBean.setBase64(ImageBase64Utils.getImgStr(multiMediaBean.getMediaFile()));
			resourcesMap.put(multiMediaBean.getId(), multiMediaBean.getBase64());
			multiMediaBeanList.add(multiMediaBean);
		}
		documentResBean.setMultiMediaList(multiMediaBeanList);
	}

	/**
	 * 将文件重命名 @Time:2020年4月6日 - 上午8:07:55 @auto:李德才 @param: @param filePath @return:
	 * void @throws
	 */
	public static String copyAndRenameFile(String filePath) {
		File file = new File(filePath);
		String zipFilePath = filePath.replace(".ofd", ".zip");
		File cpoyFile = new File(zipFilePath);
		try {
			Files.copy(file.toPath(), cpoyFile.toPath());
		} catch (IOException e) {
			e.printStackTrace();
		}
		return zipFilePath;
	}

	/**
	 * 读取资源XML @Time:2020年4月5日 - 下午7:53:01 @auto:李德才 @param: @param
	 * publicResPath @param: @throws DocumentException @return: void @throws
	 */
	public static void readPubilcRes(String publicResPath, PublicResXmlBean publicResXmlBean,Map<String,String> resourcesMap) throws DocumentException {
		SAXReader reader = new SAXReader();
		File file = new File(publicResPath);
		Document document = reader.read(file);
		Element root = document.getRootElement();
		Element fonts = root.element("Fonts");
		String publicResFolderPath = root.attributeValue("BaseLoc");
		List<Element> fontXmlList = fonts.elements();
		List<FontBean> fontList = new ArrayList<FontBean>();
		FontBean fontBean = new FontBean();
		String fontFilePath = publicResPath.substring(0, publicResPath.lastIndexOf(File.separator));
		Font fontObj = null;
		String folderPath = convertFolderPath(publicResPath);
		for (Element font : fontXmlList) {
			fontObj = Loadfont.loadFont(folderPath + publicResFolderPath + File.separator + font.element("FontFile").getTextTrim());
			fontBean.setFontName(fontObj.getFontName());
			fontBean.setFontFile(font.element("FontFile").getTextTrim());
			fontBean.setFontFilePath(fontFilePath + File.separator + "Res" + File.separator + font.element("FontFile").getTextTrim());
			fontBean.setId(font.attributeValue("ID"));
			fontList.add(fontBean);
			resourcesMap.put(fontBean.getId(), fontBean.getFontName());
		}
		publicResXmlBean.setFontList(fontList);
	}

	/**
	 * 转换路径 @Time:2020年4月11日 - 下午8:55:05 @auto:李德才 @param: @param
	 * filePath @param: @return @return: String @throws
	 */
	public static String convertFolderPath(String filePath) {
		int lastIndexOf = filePath.lastIndexOf(File.separator);
		return filePath.substring(0, lastIndexOf) + File.separator;
	}

	public static void getContent(String filePath, ContentXmlBean contentXmlBean, OfdXmlBean ofdXmlBean,Map<String,String> resourcesMap)
			throws DocumentException {
		SAXReader reader = new SAXReader();
		File file = new File(filePath);
		Document document = reader.read(file);
		Element root = document.getRootElement();
		List<Element> childElements = root.elements();
		TextObjectBean textObjectBean = null;
		
		List<TextObjectBean> textObjectBeanList = null;
		ImageObjectBean imageObjectBean = null;
		List<ImageObjectBean> imageObjectBeanList = null;
		LayerBean layerBean = null;
		List<LayerBean> layerBeanList = null;
		Element objElement = null;
		for (Element content : childElements) {
			if ("Content".equalsIgnoreCase(content.getName())) {
				List<Element> layerList = content.elements();
				layerBeanList = new ArrayList<LayerBean>();
				for (Element layer : layerList) {
					layerBean = new LayerBean();
					List<Element> tagObjectList = layer.elements();
					textObjectBeanList = new ArrayList<TextObjectBean>();
					imageObjectBeanList = new ArrayList<ImageObjectBean>();
					for (Element tagObject : tagObjectList) {
						if ("TextObject".equalsIgnoreCase(tagObject.getName())) {
							textObjectBean = new TextObjectBean();
							textObjectBean.setFontId(Integer.valueOf(tagObject.attributeValue("Font")));
							textObjectBean.setFontSize(Double.valueOf(tagObject.attributeValue("Size")));
							textObjectBean.setBoundary(tagObject.attributeValue("Boundary"));
//							textObjectBean.setFontName(convertFontName(tagObject.attributeValue("Font"), ofdXmlBean));
							textObjectBean.setFontName(resourcesMap.get(textObjectBean.getFontId().toString()));
//							TextCode
							objElement = tagObject.element("TextCode");
							textObjectBean.setText(objElement.getTextTrim());
							textObjectBean.setX(Double.valueOf(checkString(objElement.attributeValue("X"))));
							textObjectBean.setY(Double.valueOf(checkString(objElement.attributeValue("Y"))));
//							FillColor
							if (tagObject.element("FillColor") != null) {
								textObjectBean.setFillColor(checkString(tagObject.element("FillColor").attributeValue("Value")));
							}
//							CGTransform
							objElement = tagObject.element("CGTransform");
							if (objElement != null) {
								textObjectBean.setCodeCount(Integer.valueOf(checkString(objElement.attributeValue("CodeCount"))));
								textObjectBean.setCodePosition(Integer.valueOf(checkString(objElement.attributeValue("CodePosition"))));
								textObjectBean.setGlyphCount(Integer.valueOf(checkString(objElement.attributeValue("GlyphCount"))));
							}
							if (tagObject.element("CGTransform") != null&& tagObject.element("CGTransform").elementText("Glyphs") != null) {
								textObjectBean.setGlyphs(Integer.valueOf(checkString(tagObject.element("CGTransform").elementText("Glyphs"))));
							}
							textObjectBeanList.add(textObjectBean);
						}
//						图片对象
						if ("ImageObject".equalsIgnoreCase(tagObject.getName())) {
							imageObjectBean = new ImageObjectBean();
							imageObjectBean.setBoundary(tagObject.attributeValue("Boundary"));
							imageObjectBean.setCim(tagObject.attributeValue("CTM"));
							imageObjectBean.setId(tagObject.attributeValue("ID"));
							imageObjectBean.setResourceID(tagObject.attributeValue("ResourceID"));
							imageObjectBeanList.add(imageObjectBean);
							imageObjectBean.setImageBase64(resourcesMap.get(imageObjectBean.getResourceID()));
						}
					}
					if(!textObjectBeanList.isEmpty()) {
						layerBean.setTextObjectBeanList(textObjectBeanList);
					}
					if(!imageObjectBeanList.isEmpty()) {
						layerBean.setImageObjectBeanList(imageObjectBeanList);
					}
					layerBeanList.add(layerBean);
				}
				contentXmlBean.setLayerList(layerBeanList);
			}
		}
		if (root.element("Area") != null) {
			List<Element> elements = root.element("Area").elements();
			List<physicalBoxXmlBean> physicalBoxList = new ArrayList<physicalBoxXmlBean>();
			physicalBoxXmlBean physicalBoxXmlBean = null;
			for (Element element : elements) {
				physicalBoxXmlBean = new physicalBoxXmlBean();
				physicalBoxXmlBean.setValue(element.getText().toString());
				physicalBoxList.add(physicalBoxXmlBean);
			}
			contentXmlBean.setPhysicalBoxList(physicalBoxList);
		}
	}

	/**
	 * 获取字体名称 @Time:2020年4月11日 - 下午9:08:35 @auto:李德才 @param: @param
	 * fontId @param: @param ofdXmlBean @param: @return @return: String @throws
	 */
	public static String convertFontName(String fontId, OfdXmlBean ofdXmlBean) {
		PublicResXmlBean publicRes = ofdXmlBean.getDocRoots().getPublicRes();
		List<FontBean> fontList = publicRes.getFontList();
		for (FontBean font : fontList) {
			if (font.getId().equals(fontId)) {
				return font.getFontName();
			}
		}
		return null;
	}

	/**
	 * 校验字符串，读取XML有时空为 空格 @Time:2020年4月5日 - 下午7:57:08 @auto:李德才 @param: @param
	 * str @param: @return @return: String @throws
	 */
	public static String checkString(String str) {
		if (str.trim().length() > 0 && str.trim() != null) {
			return str;
		}
		return "";
	}

	/**
	 * 读取OFD文件的文档根节点 @Time:2020年4月5日 - 下午7:31:10 @auto:李德才 @param: @param
	 * rootXmlPath @param: @throws DocumentException @return: void @throws
	 */
	public static void readDocument(String rootXmlPath, OfdXmlBean ofdXmlBean) throws DocumentException {
		SAXReader reader = new SAXReader();
		File file = new File(rootXmlPath);
		Document document = reader.read(file);
//		获取跟节点
		Element root = document.getRootElement();
//		PAGE  <ofd:Pages>
		Element element = root.element("Pages");
		List<Element> elements = element.elements();
		List<ContentXmlBean> contentXmlBeanList = new ArrayList<ContentXmlBean>();
		ContentXmlBean contentXmlBean = null;
		for (Element page : elements) {
			contentXmlBean = new ContentXmlBean();
			contentXmlBean.setPath(page.attributeValue("BaseLoc"));
			contentXmlBeanList.add(contentXmlBean);
		}
		ofdXmlBean.getDocRoots().setContentXmlBeanList(contentXmlBeanList);
//		CommonData
		element = root.element("CommonData");
//		读取公共资源,实例文件中只发现一个节点，但是文档中提到 每一个节点，暂时以List存储
		element = element.element("PublicRes");
		PublicResXmlBean publicResXmlBean = new PublicResXmlBean();
		publicResXmlBean.setPath(element.getTextTrim());
		ofdXmlBean.getDocRoots().setPublicRes(publicResXmlBean);
//		读取文档资源列表
		element = root.element("CommonData");
		element = element.element("DocumentRes");
//		有资源
		if (element != null) {
			DocumentResBean documentResBean = new DocumentResBean();
			documentResBean.setPath(element.getTextTrim());
			ofdXmlBean.getDocRoots().setDocumentRes(documentResBean);
		}

//		获取该文档页面区域的默认大小和位置,应该是一个，但是XML中的格式是可以兼容多个标签的，使用List存储
		element = root.element("CommonData");
		element = element.element("PageArea").element("PhysicalBox");
		List<String> physicalBoxList = new ArrayList<String>();
		physicalBoxList.add(element.getTextTrim());
		ofdXmlBean.getDocRoots().setPhysicalBoxList(physicalBoxList);
	}

	/**
	 * 获取根节点文档位置 @Time:2020年4月5日 - 下午1:19:42 @auto:李德才 @param: @param
	 * filderPath @param: @return @param: @throws DocumentException @return:
	 * String @throws
	 */
	public static void getRootXmlPathList(String filderPath, OfdXmlBean ofdXmlBean) throws DocumentException {
		String xmlPath = filderPath + File.separator + OFD_XML_NAME;
		SAXReader reader = new SAXReader();
		File file = new File(xmlPath);
		Document document = reader.read(file);
		Element root = document.getRootElement();
		List<Element> childElements = root.elements();
		DocumentXmlBean documentXmlBean = null;
		for (Element element : childElements) {
			documentXmlBean = new DocumentXmlBean();
			documentXmlBean.setPath(element.elementText("DocRoot"));
			ofdXmlBean.setDocRoots(documentXmlBean);
		}
	}

}
